package com.agh.portal.service;


import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;

import com.agh.portal.domain.Ad;
import com.agh.portal.domain.AghGroup;
import com.agh.portal.domain.Answer;
import com.agh.portal.domain.Comment;
import com.agh.portal.domain.Course;
import com.agh.portal.domain.CourseStudent;
import com.agh.portal.domain.Faculty;
import com.agh.portal.domain.GroupEvent;
import com.agh.portal.domain.MainPagePost;
import com.agh.portal.domain.Post;
import com.agh.portal.domain.Question;
import com.agh.portal.domain.Reply;
import com.agh.portal.domain.Student;
import com.agh.portal.domain.enumeration.AdvertisementCategory;
import com.agh.portal.domain.enumeration.Gender;
import com.agh.portal.domain.enumeration.PostCategory;
import com.agh.portal.domain.enumeration.StudentStatus;
import com.agh.portal.domain.security.Role;
import com.agh.portal.domain.util.CustomDateUtils;

public class Bootstrap implements InitializingBean{
	private transient final Log log = LogFactory.getLog(getClass());
	
	@Autowired
	private PlatformTransactionManager transactionManager;
	
	@Autowired
	private SecurityUtils userService;

	public Bootstrap() {

	}
	
	private boolean guestUserExists() {
		return Student.findStudent(1l) != null;
	}
	
	protected void insertBoostrapData(){
		// if the guest user account exists, take this as a sign that the
		// bootstrap data populator has
		// already been run, so just exit quietly:
		if (guestUserExists()) {
			if (log.isDebugEnabled()) {
				log.debug("Bootstrap data insertion has already occurred. Returning quietly.");
			}
			return;
		}
		
		log.info("Inserting bootstrap data...");
		
		initializeSecurity();
		createStudents();
		createFaculties();
		createGroups();
		createMainPagePosts();
		createQuestions();
		createAds();

		log.info("Done inserting bootstrap data.");
	}
	
	private void initializeSecurity(){
		Role role = new Role();
		role.setName("ROLE_USER");
		role.setDescription("Simple user role");
		role.persist();
		
		role = new Role();
		role.setName("ROLE_ADMIN");
		role.setDescription("Admin role");
		role.persist();
		
		userService.createAdminAcc("admin@portal.agh.pl", "admin");
		admin = new Student();
		admin.setName("Admin");
		admin.setSurname("Admin");
		admin.setCityOfOrigin("Test");
		admin.setDateOfBirth(CustomDateUtils.getBirthDate(1988, 5, 24));
		admin.setEmail("admin@portal.agh.pl");
		admin.setStudentStatus(StudentStatus.Graduate);
		admin.setGender(Gender.Male);
		admin.setAvatarId("avatar-blank-128.jpg");
		admin.persist();
	}
	
	private void createStudents(){
		
		userService.createUserAcc("kojtarafal@gmail.com", "password");
		rafcio = new Student();
		rafcio.setName("Rafał");
		rafcio.setSurname("Kojta");
		rafcio.setCityOfOrigin("Białystok");
		rafcio.setDateOfBirth(CustomDateUtils.getBirthDate(1988, 5, 24));
		rafcio.setEmail("kojtarafal@gmail.com");
		rafcio.setStudentStatus(StudentStatus.Graduate);
		rafcio.setGender(Gender.Male);
		rafcio.setAvatarId("avatar-blank-128.jpg");
		rafcio.persist();
		
		userService.createUserAcc("erjon@gmail.com", "password");
		erjoni = new Student();
		erjoni.setName("Erjon");
		erjoni.setSurname("Bebja");
		erjoni.setEmail("erjon@gmail.com");
		erjoni.setStudentStatus(StudentStatus.Student);
		erjoni.setGender(Gender.Male);
		erjoni.setAvatarId("avatar-blank-128.jpg");
		erjoni.persist();
		
		userService.createUserAcc("mario@gmail.com", "password");
		mario = new Student();
		mario.setName("Mariglen");
		mario.setSurname("Noizzie");
		mario.setEmail("mario@gmail.com");
		mario.setStudentStatus(StudentStatus.Undefined);
		mario.setGender(Gender.Male);
		mario.setAvatarId("avatar-blank-128.jpg");
		mario.persist();
		
		userService.createUserAcc("test@test.test", "test");
		test = new Student();
		test.setName("Test");
		test.setSurname("Test");
		test.setCityOfOrigin("Test");
		test.setDateOfBirth(CustomDateUtils.getBirthDate(1988, 5, 24));
		test.setEmail("test@test.test");
		test.setStudentStatus(StudentStatus.Graduate);
		test.setGender(Gender.Male);
		test.setAvatarId("avatar-blank-128.jpg");
		test.persist();
	}
	
	private void createFaculties(){
		Faculty faculty1 = new Faculty();
		faculty1.setShortName("WEAIiIB");
		faculty1.setName("Wydział Elektrotechniki, Automatyki, Informatyki i Inżynierii Biomedycznej");
		faculty1.setLogoId("WEAIiIB.jpg");
		faculty1.setWebAddress("http://www.eaiib.agh.edu.pl/");
		faculty1.persist();
		createCourses(faculty1);
		
		Faculty faculty2 = new Faculty();
		faculty2.setShortName("WGiG");
		faculty2.setName("Wydział Górnictwa i Geoinżynierii");
		faculty2.setLogoId("WGiG.jpg");
		faculty2.setWebAddress("http://www.gorn.agh.edu.pl/");
		faculty2.persist();
		createCourses(faculty2);
		
		Faculty faculty3 = new Faculty();
		faculty3.setShortName("WIMiIP");
		faculty3.setName("Wydział Inżynierii Metali i Informatyki Przemysłowej");
		faculty3.setLogoId("WIMiIP.jpg");
		faculty3.setWebAddress("http://www.metal.agh.edu.pl/");
		createCourses(faculty3);
		faculty3.persist();
		
		Faculty faculty4 = new Faculty();
		faculty4.setShortName("WIMiR");
		faculty4.setName("Wydział Inżynierii Mechanicznej i Robotyki");
		faculty4.setLogoId("WIMiR.jpg");
		faculty4.setWebAddress("http://www.imir.agh.edu.pl/");
		createCourses(faculty4);
		faculty4.persist();
		
		Faculty faculty5 = new Faculty();
		faculty5.setShortName("WGGiOŚ");
		faculty5.setName("Wydział Geologii, Geofizyki i Ochrony Środowiska");
		faculty5.setLogoId("WGGiOS.jpg");
		faculty5.setWebAddress("http://www.wggios.agh.edu.pl/");
		createCourses(faculty5);
		faculty5.persist();
		
		Faculty faculty6 = new Faculty();
		faculty6.setShortName("WGGiIŚ");
		faculty6.setName("Wydział Geodezji Górniczej i Inżynierii Środowiska");
		faculty6.setLogoId("WGGiIS.jpg");
		faculty6.setWebAddress("http://www.geod.agh.edu.pl/");
		createCourses(faculty6);
		faculty6.persist();
		
		Faculty faculty7 = new Faculty();
		faculty7.setShortName("WIMiC");
		faculty7.setName("Wydział Inżynierii Materiałowej i Ceramiki");
		faculty7.setLogoId("WIMiC.jpg");
		faculty7.setWebAddress("http://www.ceramika.agh.edu.pl /");
		createCourses(faculty7);
		faculty7.persist();
		
		Faculty faculty8 = new Faculty();
		faculty8.setShortName("WO");
		faculty8.setName("Wydział Odlewnictwa");
		faculty8.setLogoId("WO.jpg");
		faculty8.setWebAddress("http://www.odlewnictwo.agh.edu.pl/");
		createCourses(faculty8);
		faculty8.persist();
		
		Faculty faculty9 = new Faculty();
		faculty9.setShortName("WMN");
		faculty9.setName("Wydział Metali Nieżelaznych");
		faculty9.setLogoId("WMN.jpg");
		faculty9.setWebAddress("http://www.wmn.agh.edu.pl/");
		createCourses(faculty9);
		faculty9.persist();
		
		Faculty faculty10 = new Faculty();
		faculty10.setShortName("WWNiG");
		faculty10.setName("Wydział Wiertnictwa, Nafty i Gazu");
		faculty10.setLogoId("WWNiG.jpg");
		faculty10.setWebAddress("http://www.wnig.agh.edu.pl/");
		createCourses(faculty10);
		faculty10.persist();
		
		Faculty faculty11 = new Faculty();
		faculty11.setShortName("WZ");
		faculty11.setName("Wydział Zarządzania");
		faculty11.setLogoId("WZ.jpg");
		faculty11.setWebAddress("http://www.zarz.agh.edu.pl/");
		createCourses(faculty11);
		faculty11.persist();
		
		Faculty faculty12 = new Faculty();
		faculty12.setShortName("WFiIS");
		faculty12.setName("Wydział Fizyki i Informatyki Stosowanej");
		faculty12.setLogoId("WFiIS.jpg");
		faculty12.setWebAddress("http://www.fis.agh.edu.pl/");
		createCourses(faculty12);
		faculty12.persist();
		
		Faculty faculty13 = new Faculty();
		faculty13.setShortName("WMS");
		faculty13.setName("Wydział Matematyki Stosowanej");
		faculty13.setLogoId("WMS.jpg");
		faculty13.setWebAddress("http://www.wms.agh.edu.pl/");
		createCourses(faculty13);
		faculty13.persist();
		
		Faculty faculty14 = new Faculty();
		faculty14.setShortName("WH");
		faculty14.setName("Wydział Humanistyczny");
		faculty14.setLogoId("WH.jpg");
		faculty14.setWebAddress("http://www.wh.agh.edu.pl/");
		createCourses(faculty14);
		faculty14.persist();
		
		Faculty faculty15 = new Faculty();
		faculty15.setShortName("WEiP");
		faculty15.setName("Wydział Energetyki i Paliw");
		faculty15.setLogoId("WEiP.jpg");
		faculty15.setWebAddress("http://www.weip.agh.edu.pl/");
		createCourses(faculty15);
		faculty15.persist();
		
		Faculty faculty16 = new Faculty();
		faculty16.setShortName("WIEiT");
		faculty16.setName("Wydział Informatyki, Elektroniki i Telekomunikacji");
		faculty16.setLogoId("WIEiT.jpg");
		faculty16.setWebAddress("http://www.iet.agh.edu.pl/");
		createCourses(faculty16);
		faculty16.persist();
	}
	
	private void createCourses(Faculty faculty){
		for(int i=0;i<3;i++){
			Course course = new Course();
			course.setName(loremTitle);
			course.setFaculty(faculty);
			course.setStartYear(2010+i);
			course.persist();
		
			Course course2 = new Course();
			course2.setName(loremTitle);
			course2.setFaculty(faculty);
			course2.setStartYear(2010+i);
			course2.persist();
			createCourseStudens(course2);
			createGroup(course2);
		}
	}
	
	private void createCourseStudens(Course course){
		CourseStudent cs1 = new CourseStudent();
		cs1.setCourse(course);
		cs1.setStudent(erjoni);
		cs1.persist();
		
		CourseStudent cs2 = new CourseStudent();
		cs2.setCourse(course);
		cs2.setStudent(rafcio);
		cs2.persist();
		
		CourseStudent cs3 = new CourseStudent();
		cs3.setCourse(course);
		cs3.setStudent(mario);
		cs3.persist();
	}
	
	private void createGroups(){
		AghGroup group1 = new AghGroup();
		group1.setName(loremTitle);
		group1.setDescription(loremDesc);
		group1.persist();

		createPosts(group1);
		createGroupEvents(group1);
		List<Student> students = Student.findStudentEntries(0, 10);
		for(Student s : students){
			group1.getStudents().add(s);
		}
		group1.persist();
		
		AghGroup emptyGroup = new AghGroup();
		emptyGroup.setName(loremTitle);
		emptyGroup.setDescription(loremDesc);
		emptyGroup.persist();
	}
	
	private void createGroup(Course course){
		AghGroup group = new AghGroup();
		group.setName("Year group course " + course.getName() + " " + course.getStartYear());
		group.setDescription(loremDesc);
		group.setCourse(course);
		group.setLogoId("unknown-64-64.png");
		
		Set<Student> moderators = new HashSet<Student>();
		moderators.add(rafcio);
		moderators.add(erjoni);
		moderators.add(mario);
		moderators.add(test);
		group.setModerators(moderators);
		group.getStudents().add(mario);
		group.getStudents().add(test);
		group.getInvitedStudents().add(erjoni);
		group.persist();
	}
	
	private void createPosts(AghGroup group) {
		for (int i = 0; i < 2; i++) {
			Post post = new Post();
			post.setTitle(loremTitle);
			post.setContent(loremTextLong);
			post.setPostDate(CustomDateUtils.getRandomDate());
			post.setAghGroup(group);
			post.setStudent(rafcio);
			post.persist();
			for (int j = 0; j < 3; j++) {
				createReply(post, i);
			}
		}
	}
	
	private void createReply(Post post, int n){
		Reply reply = new Reply();
		reply.setContent(n + loremText);
		reply.setReplyDate(CustomDateUtils.getRandomDate());
		reply.setStudent(erjoni);
		reply.setPost(post);
		reply.persist();
	}
	
	private void createGroupEvents(AghGroup group){
		for(int i=0;i<5;i++){
			GroupEvent event = new GroupEvent();
			event.setAghGroup(group);
			event.setTitle(loremTitle);
			event.setEventDate(CustomDateUtils.getRandomDate());
			event.setContent(loremText);
			event.setStudent(mario);
			event.persist();
		}
		
	}
	
	private void createMainPagePosts(){
		MainPagePost post1 = new MainPagePost();
		post1.setBadVoteCount(3);
		post1.setGoodVoteCount(5);
		post1.setCategory(PostCategory.News);
		post1.setTitle("1 " + loremTitle);
		post1.setSubtitle(loremShortDesc);
		post1.setContent(loremTextLong);
		post1.setStudent(rafcio);
		post1.setCreationDate(CustomDateUtils.getRandomDate());
		post1.persist();
		createComments(post1);
		
		MainPagePost post2 = new MainPagePost();
		post2.setBadVoteCount(0);
		post2.setGoodVoteCount(0);
		post2.setCategory(PostCategory.Event);
		post2.setTitle("2 " + loremTitle);
		post2.setSubtitle(loremShortDesc);
		post2.setContent(loremTextLong);
		post2.setStudent(erjoni);
		post2.setCreationDate(CustomDateUtils.getRandomDate());
		post2.persist();
		createComments(post2);
		
		MainPagePost post3 = new MainPagePost();
		post3.setBadVoteCount(6);
		post3.setGoodVoteCount(2);
		post3.setCategory(PostCategory.Party);
		post3.setTitle("3 " + loremTitle);
		post3.setSubtitle(loremShortDesc);
		post3.setContent(loremTextLong);
		post3.setStudent(mario);
		post3.setCreationDate(CustomDateUtils.getRandomDate());
		post3.persist();
		createComments(post3);
	}
	
	private void createComments(MainPagePost post){
		for(int i = 0;i<10;i++){
			Comment comment = new Comment();
			comment.setStudent(rafcio);
			comment.setContent(post.getId() + loremText);
			comment.setGoodVoteCount(5+i);
			comment.setBadVoteCount(10-i);
			comment.setMainPagePost(post);
			comment.setCreationDate(CustomDateUtils.getRandomDate());
			comment.persist();
		}
	}
	
	private void createAds(){
		Ad ad = new Ad();
		ad.setStudent(rafcio);
		ad.setTitle(loremTitle);
		ad.setContent(loremText);
		ad.setCreationDate(CustomDateUtils.getRandomDate());
		ad.setCategory(AdvertisementCategory.Borrow);
		ad.persist();
		
		Ad ad2 = new Ad();
		ad2.setStudent(rafcio);
		ad2.setTitle(loremTitle);
		ad2.setContent(loremText);
		ad2.setCreationDate(CustomDateUtils.getRandomDate());
		ad2.setCategory(AdvertisementCategory.Buy);
		ad2.persist();
		
		Ad ad3 = new Ad();
		ad3.setStudent(erjoni);
		ad3.setTitle(loremTitle);
		ad3.setContent(loremText);
		ad3.setCreationDate(CustomDateUtils.getRandomDate());
		ad3.setCategory(AdvertisementCategory.Borrow);
		ad3.persist();
		
		Ad ad4 = new Ad();
		ad4.setStudent(mario);
		ad4.setTitle(loremTitle);
		ad4.setContent(loremText);
		ad4.setCreationDate(CustomDateUtils.getRandomDate());
		ad4.setCategory(AdvertisementCategory.Offer);
		ad4.persist();
	}
	
	private void createQuestions(){
		Question question1 = new Question();
		question1.setTitle("1 " + loremTitle);
		question1.setContent(loremText);
		question1.setBadVoteCount(10);
		question1.setGoodVoteCount(20);
		question1.setCreationDate(CustomDateUtils.getRandomDate());
		question1.setStudent(rafcio);
		question1.persist();
		createAnswers(question1);
		
		Question question2 = new Question();
		question2.setTitle("2 " + loremTitle);
		question2.setContent(loremText);
		question2.setBadVoteCount(20);
		question2.setGoodVoteCount(10);
		question2.setCreationDate(CustomDateUtils.getRandomDate());
		question2.setStudent(erjoni);
		question2.persist();
		createAnswers(question2);	
	}
	
	private void createAnswers(Question question){
		for (int i = 0; i < 5; i++) {
			Answer answer = new Answer();
			answer.setStudent(rafcio);
			answer.setContent(loremText);
			answer.setGoodVoteCount(i+2);
			answer.setBadVoteCount(5-i);
			answer.setQuestion(question);
			answer.setCreationDate(CustomDateUtils.getRandomDate());
			answer.persist();
		}
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		log.info("Running data Bootstrap...");
		
		if (this.transactionManager == null) {
			throw new IllegalStateException("transactionManager property must be set.");
		}
		// assert other injected dependencies here

		TransactionTemplate txnTemplate = new TransactionTemplate(this.transactionManager);
		txnTemplate.afterPropertiesSet();

		txnTemplate.execute(new TransactionCallback() {
			public Object doInTransaction(TransactionStatus status) {
				try {
					insertBoostrapData();
				} catch (Exception e) {
					// error - roll back. Runtime exception triggers rollback:
					if (e instanceof RuntimeException) {
						throw (RuntimeException) e;
					} else {
						throw new RuntimeException(e);
					}
				}
				return null;
			}
		});
	}
	
	private Student rafcio;
	private Student erjoni;
	private Student mario;
	private Student test;
	private Student admin;
	private static String loremTitle = "Lorem ipsum dolor sit amet";
	private static String loremShortDesc = "Proin nibh augue, suscipit a, scelerisque sed, lacinia in, mi. Cras vel lorem. Etiam pellentesque aliquet tellus. Phasellus pharetra nulla ac diam. ";
	private static String loremDesc= "Quisque semper justo at risus. Donec venenatis, turpis vel hendrerit interdum, dui ligula ultricies purus, sed posuere libero dui id orci. Nam congue, pede vitae dapibus aliquet, elit magna vulputate arcu, vel tempus metus leo non est. Etiam sit amet lectus quis est congue mollis. Phasellus congue lacus eget neque.";
	private static String loremText = "Lorem ipsum dolor sit amet, consectetur adipisicing elit. Proin nibh augue, suscipit a, scelerisque sed, lacinia in, mi. Cras vel lorem. Etiam pellentesque aliquet tellus. Phasellus pharetra nulla ac diam. Quisque semper justo at risus. Donec venenatis, turpis vel hendrerit interdum, dui ligula ultricies purus, sed posuere libero dui id orci. Nam congue, pede vitae dapibus aliquet, elit magna vulputate arcu, vel tempus metus leo non est. Etiam sit amet lectus quis est congue mollis. Phasellus congue lacus eget neque. Phasellus ornare, ante vitae consectetuer consequat, purus sapien ultricies dolor, et mollis pede metus eget nisi. Praesent sodales velit quis augue. Cras suscipit, urna at aliquam rhoncus, urna quam viverra nisi, in interdum massa nibh nec erat.";
	private static String loremTextLong = "Sed ut perspiciatis, unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam eaque ipsa, quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt, explicabo. Nemo enim ipsam voluptatem, quia voluptas sit, aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos, qui ratione voluptatem sequi nesciunt, neque porro quisquam est, qui dolorem ipsum, quia dolor sit, amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt, ut labore et dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit, qui in ea voluptate velit esse, quam nihil molestiae consequatur, vel illum, qui dolorem eum fugiat, quo voluptas nulla pariatur? [33] At vero eos et accusamus et iusto odio dignissimos ducimus, qui blanditiis praesentium voluptatum deleniti atque corrupti, quos dolores et quas molestias excepturi sint, obcaecati cupiditate non provident, similique sunt in culpa, qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio, cumque nihil impedit, quo minus id, quod maxime placeat, facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet, ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat.";
	
}
